package com.openatc.extend.common.aop.log;

import com.openatc.extend.common.aop.model.SysLog;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;

/**
 * @author ：panleilei
 * @description
 * @modified By：
 * @version:
 * @date ：Created in 2023/3/23 16:51
 */
@Component
public class SysLogProcessor {
    private static final Logger logger = Logger.getLogger(SysLogProcessor.class.getSimpleName());
    private final Map<Class<? extends Collector>, Collector> collectors = new HashMap<>();
    private final Map<Class<? extends DataExtractor>, DataExtractor> extractors = new HashMap<>();


    @Autowired
    private CollectorExecutor collectorExecutor;

    @Autowired
    private ApplicationContext applicationContext;


    public Object proceed(ProceedingJoinPoint point) throws Throwable {
        Object ret = null;
        try {
            ret = point.proceed();
            return ret;
        } catch (Throwable throwable) {
            logger.warning("Aop error! " + throwable.getMessage());
            ret = throwable.getMessage();
            throw throwable;
        } finally {
            // 捕获记录日志时出现的异常，保证接口的正常应答
            try {
                MethodSignature signature = (MethodSignature) point.getSignature();
                SysLog sysLog = signature.getMethod().getAnnotation(SysLog.class);
                if (sysLog == null) {
                    sysLog = point.getTarget().getClass().getAnnotation(SysLog.class);
                }
                if (sysLog != null) {
                    // 记录日志
                    collectorExecutor.execute(selectCollector(sysLog.collector()),point,selectExtractor(sysLog.extractor()),ret);
                }
            } catch (Exception e) {
                logger.warning("Aop collect log error! " + e.getMessage());
            }
        }
    }


    /**
     * 选择一个收集器
     */
    private Collector selectCollector(Class<? extends Collector> clz) {

        Collector collector;
        try {
            collector = applicationContext.getBean(clz);
        } catch (Exception e) {
            collector = collectors.get(clz);
            if (collector == null) {
                collector = BeanUtils.instantiateClass(clz);
                collectors.put(clz, collector);
            }
        }
        return collector;
    }

    private DataExtractor selectExtractor(Class<? extends DataExtractor> clz) {

        DataExtractor dataExtractor;
        try {
            dataExtractor = applicationContext.getBean(clz);
        } catch (Exception e) {
            dataExtractor = extractors.get(clz);
            if (dataExtractor == null) {
                dataExtractor = BeanUtils.instantiateClass(clz);
                extractors.put(clz, dataExtractor);
            }
        }
        return dataExtractor;
    }
}
